package com.wlyuan.open.scanner.repository.impl;

import com.wlyuan.open.scanner.assembler.ScannerTransportAssembler;
import com.wlyuan.open.scanner.assembler.ScannerTransportRelationAssembler;
import com.wlyuan.open.scanner.constant.Constants;
import com.wlyuan.open.scanner.dao.entity.OrderIndexDO;
import com.wlyuan.open.scanner.dao.mapper.OrderIndexMapper;
import com.wlyuan.open.scanner.domain.transport.Transport;
import com.wlyuan.open.scanner.domain.transport.TransportConvert;
import com.wlyuan.open.scanner.domain.transport.TransportIdRelation;
import com.wlyuan.open.scanner.domain.transport.TransportRelationConvert;
import com.wlyuan.open.scanner.repository.OrderExceptionRepository;
import com.wlyuan.open.scanner.repository.TransportRepository;
import com.wlyuan.open.scanner.repository.WayBillRepository;
import com.wlyuan.open.scanner.utils.enums.bill.TransportBillStatusEnum;
import com.wlyuan.open.scanner.utils.enums.order.OrderSplitMarkEnum;
import com.wlyuan.open.scanner.utils.enums.order.OrderSrcClassEnum;
import com.wlyuan.open.scanner.utils.enums.order.OrderStatusEnum;
import com.wlyuan.open.scanner.utils.enums.transport.TransportReceiptReviewEnum;
import com.wlyuan.open.scanner.utils.enums.transport.TransportStatusEnum;
import com.wlyuan.open.scanner.utils.enums.transport.TransportTypeEnum;
import com.wlyuan.open.utils.LongUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author lijing
 * @description
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class TransportRepositoryImpl implements TransportRepository {
    private final OrderIndexMapper orderIndexMapper;
    private final BaseOrderRepository baseOrderRepository;
    private final OrderExceptionRepository orderExceptionRepository;
    private final WayBillRepository wayBillRepository;
    private final BaseCostRepository baseCostRepository;

    @Override
    public void sync() {
        logger.info("(Index_Status <> -1 and Index_Status <> 0 and Index_SrcClass = 2) or (Index_SrcClass = 1 and Index_SrcOrderID = 0)");

        var count = wayBillRepository.count();
        logger.info("运单老数据数据量，size：{}", count);
        var pages = (int) Math.ceil(count * 1.0 / Constants.PAGE_SIZE);
        for (int i = 1; i <= pages; i++) {
            logger.info("开始同步运单数据：第{}页，共{}页", i, pages);
            var list = wayBillRepository.list(i);
            list.forEach(data -> {
                try {
                    var ts = parse(data.getUp(), data.getDown());
                    baseOrderRepository.sync(ScannerTransportAssembler.assemble(ts));
                } catch (Exception e) {
                    logger.error("运单同步异常：{},{}", data.getUp(), e.getMessage());
                    e.printStackTrace();
                }
            });
        }
        logger.info("运单同步完成......");
    }

    @Override
    public List<Transport> transportList() {
        return Collections.emptyList();
    }

    @Override
    public Transport getById(Long transportId) {
        return Optional.ofNullable(transportId).map(id -> {
            var wayBill = wayBillRepository.getByUp(id);
            if (!Optional.ofNullable(wayBill).isPresent()) {
                wayBill = wayBillRepository.getByDown(id);
            }
            return Optional.ofNullable(wayBill).map(data -> parse(data.getUp(), data.getDown())).orElse(null);
        }).orElse(null);
    }

    @Override
    public void getByTenantId(Long tenantId) {
        logger.info("(Index_Status <> -1 and Index_Status <> 0 and Index_SrcClass = 2) or (Index_SrcClass = 1 and Index_SrcOrderID = 0)");
        var count = wayBillRepository.count(tenantId);
        logger.info("租户{}运单老数据数据量，size：{}", tenantId, count);
        var pages = (int) Math.ceil(count * 1.0 / Constants.PAGE_SIZE);
        for (int i = 1; i <= pages; i++) {
            logger.info("开始同步租户{}运单数据：第{}页，共{}页", tenantId, i, pages);
            var list = wayBillRepository.list(i, tenantId);
            list.forEach(data -> {
                try {
                    var ts = parse(data.getUp(), data.getDown());
                    baseOrderRepository.sync(ScannerTransportAssembler.assemble(ts));
                } catch (Exception e) {
                    logger.error("运单同步异常：{},{}", data.getUp(), e.getMessage());
                    e.printStackTrace();
                }
            });
        }
        logger.info("租户{}运单同步完成......", tenantId);
    }

    @Override
    public Transport getCarrierCustomer(Long transportId) {
        return Optional.ofNullable(transportId).map(id -> {
            var wayBill = wayBillRepository.getByUp(id);
            if (!Optional.ofNullable(wayBill).isPresent()) {
                wayBill = wayBillRepository.getByDown(id);
            }
            return Optional.ofNullable(wayBill).map(data -> parseCarrierCustomer(data.getUp(), data.getDown())).orElse(null);
        }).orElse(null);
    }

    public Transport parseCarrierCustomer(Long up, Long down) {
        var data = orderIndexMapper.getById(up);
        baseOrderRepository.processCarrier(data);
        var ts = TransportConvert.convert(data, down);

        if (OrderSrcClassEnum.isOrder(data.getIndexSrcclass())) {
            ts.setCustomer(TransportConvert.convertCustomer(data));
        }
        if (OrderSrcClassEnum.isTransport(data.getIndexSrcclass())) {
            //有承运方时
            if (LongUtils.notNullLong(data.getIndexSupplierid()) || LongUtils.notNullLong(data.getIndexSuppliersymbolid()) || LongUtils.notNullLong(data.getIndexDriverid())) {
                //状态16 默认为待签收
                if (OrderStatusEnum.ALREADY.getValue().equals(data.getIndexStatus())) {
                    data.setTransportStatus(TransportStatusEnum.WAIT_SIGN.getValue());
                }
                ts.setCarrier(TransportConvert.convertCarrier(data));
            }
            //无承运方,无下游，状态为待调度
            if (!LongUtils.notNullLong(data.getIndexSupplierid()) && !LongUtils.notNullLong(data.getIndexSuppliersymbolid()) && !LongUtils.notNullLong(data.getIndexDriverid()) && !LongUtils.notNullLong(down)
                    && (OrderStatusEnum.WAIT_SIGN.getValue().equals(data.getIndexStatus()) || OrderStatusEnum.DONE.getValue().equals(data.getIndexStatus()))) {
                data.setTransportStatus(OrderStatusEnum.WAIT_DISPATCH.getValue());
            }
            ts.setCustomer(TransportConvert.convertCustomer(data));

            if (LongUtils.notNullLong(down)) {
                var downData = orderIndexMapper.getById(down);
                Optional.ofNullable(downData).ifPresent(d -> {
                    baseOrderRepository.processCarrier(d);
                    //状态16 默认为待签收
                    if (OrderStatusEnum.ALREADY.getValue().equals(d.getIndexStatus())) {
                        d.setTransportStatus(TransportStatusEnum.WAIT_SIGN.getValue());
                    }
                    //承运方信息特殊处理
                    if (ts.getCarrier() == null) {
                        baseOrderRepository.processCarrier(d, data.getIndexCreatorcompanyid());
                        ts.setCarrier(TransportConvert.convertCarrier(d));
                        //无承运方 和 司机
                        if (ts.getCarrier() != null && ts.getCarrier().getCarrierType() == null) {
                            ts.setCarrier(null);
                        }
                    }
                    ts.setCustomer(TransportConvert.convertCustomer(d));
                });
            }
        }
        return ts;
    }

    @Override
    public Transport parse(Long up, Long down) {
        var data = orderIndexMapper.getById(up);
        if (baseOrderRepository.checkTenant(data.getIndexCreatorcompanyid())) {
            logger.error("运单id：{},租户id:{}", up, data.getIndexCreatorcompanyid());
            return null;
        }
        if (OrderSrcClassEnum.isOrder(data.getIndexSrcclass())) {
            data.setCustomerFinanceStatus(data.getFinanceStatus());
        }
        if (OrderSrcClassEnum.isTransport(data.getIndexSrcclass())) {
            data.setCarrierFinanceStatus(data.getFinanceStatus());
        }
        //基础数据
        process(data, down);
        //运单对应的订单信息，用户创建物品时用
        Optional.ofNullable(orderIndexMapper.getCompanyById(data.getIndexRootorderid())).ifPresent(o -> {
            data.setOrderTenantId(o.getIndexCreatorcompanyid());
            data.setOrderCustomerId(o.getIndexCustomerid());
            data.setOrderCustomerType(o.getCustomerType());
            data.setOrderCustomerName(o.getIndexCustomername());
            data.setOrderCreateBy(o.getIndexCreator());
        });
        var ts = TransportConvert.convert(data, down);

        if (OrderSrcClassEnum.isOrder(data.getIndexSrcclass())) {
            processRelation(data);
            ts.setCustomer(TransportConvert.convertCustomer(data));
        }
        if (OrderSrcClassEnum.isTransport(data.getIndexSrcclass())) {
            processRelation(data);
            //有承运方时
            if (LongUtils.notNullLong(data.getIndexSupplierid()) || LongUtils.notNullLong(data.getIndexSuppliersymbolid()) || LongUtils.notNullLong(data.getIndexDriverid())) {
                //状态16 默认为待签收
                if (OrderStatusEnum.ALREADY.getValue().equals(data.getIndexStatus())) {
                    data.setTransportStatus(TransportStatusEnum.WAIT_SIGN.getValue());
                }
                ts.setCarrier(TransportConvert.convertCarrier(data));
            }
            //无承运方,无下游，状态为待调度
            if (!LongUtils.notNullLong(data.getIndexSupplierid()) && !LongUtils.notNullLong(data.getIndexSuppliersymbolid()) && !LongUtils.notNullLong(data.getIndexDriverid()) && !LongUtils.notNullLong(down)
                    && (OrderStatusEnum.WAIT_SIGN.getValue().equals(data.getIndexStatus()) || OrderStatusEnum.DONE.getValue().equals(data.getIndexStatus()))) {
                data.setTransportStatus(OrderStatusEnum.WAIT_DISPATCH.getValue());
            }
            ts.setCustomer(TransportConvert.convertCustomer(data));

            if (LongUtils.notNullLong(down)) {
                var downData = orderIndexMapper.getById(down);
                Optional.ofNullable(downData).ifPresent(d -> {
                    //报价状态取最大的
                    Optional.ofNullable(ts.getFinance()).ifPresent(f -> {
                        f.setFinanceFlag(TransportBillStatusEnum.fromValue(financeStatus(data.getFinanceStatus(), d.getFinanceStatus())));
                    });
                    process(d, null);
                    processRelation(d);

                    //状态16 默认为待签收
                    if (OrderStatusEnum.ALREADY.getValue().equals(d.getIndexStatus())) {
                        d.setTransportStatus(TransportStatusEnum.WAIT_SIGN.getValue());
                    }

                    //承运方信息特殊处理
                    if (ts.getCarrier() == null) {
                        baseOrderRepository.processCarrier(d, data.getIndexCreatorcompanyid());
                        ts.setCarrier(TransportConvert.convertCarrier(d));
                        //无承运方 和 司机
                        if (ts.getCarrier() != null && ts.getCarrier().getCarrierType() == null) {
                            ts.setCarrier(null);
                        }
                    }
                    ts.setCustomer(TransportConvert.convertCustomer(d));
                    /*if (ts.getClose() != null && ts.getClose().getToTenantId() != null && ts.getCustomer() != null) {
                        ts.getClose().setToTenantId(ts.getCustomer().getTenantId());
                    }*/
                });
            }
        }
        return ts;
    }

    private void process(OrderIndexDO data, Long down) {
        //地址
        baseOrderRepository.processAddress(data);
        //承运商
        baseOrderRepository.processCarrier(data);
        //调度
        baseOrderRepository.dispatch(data);
        //关单
        baseOrderRepository.close(data);
        //补差
        baseOrderRepository.valueAddition(data);
        //物品
        data.setGoodsList(baseOrderRepository.getOrderGoodsByOrderId(data.getIndexId(), data.getIndexCreatorcompanyid()));
        //费用信息
        baseCostRepository.cost(data, down, true);
        //预付，到付，货到付款操作
        baseOrderRepository.financeFlag(data, down);
    }

    private void processRelation(OrderIndexDO data) {
        //运单状态
        transportStatus(data);
        //签单人
        baseOrderRepository.sign(data, true);
        //回单人
        baseOrderRepository.transportReceipt(data, true);
        //附件
        data.setAttachments(baseOrderRepository.attach(data.getIndexId()));
        //回单复核
        receiptReview(data);
    }

    /**
     * 上游运单id
     *
     * @param data
     */
    @Override
    public Long upTransportId(OrderIndexDO data) {
        //是否拆单
        var beSplit = Optional.ofNullable(OrderSplitMarkEnum.isSplit(data.getIndexBesplit())).orElse(false);
        if (beSplit) {
            return data.getIndexPrevorderid();
        }
        if (LongUtils.notNullLong(data.getIndexPrevorderid())) {
            return data.getIndexPrevorderid();
        }
        //来源id
        var srcOrderId = data.getIndexSrcorderid();
        if (LongUtils.notNullLong(srcOrderId)) {
            //根据srcOrderId 得到来源订单信息
            var srcOrder = orderIndexMapper.getById(srcOrderId);
            return Optional.ofNullable(srcOrder).map(src -> {
                //源订单的来源id 为 0 ，则上游运单id为当前运单的来源id，否则为当前运单来源运单的来源id
                return src.getIndexSrcorderid() == 0 ? srcOrderId : src.getIndexSrcorderid();
            }).orElse(0L);
        }
        return 0L;
    }

    /**
     * 运单状态
     *
     * @param data
     */
    private void transportStatus(OrderIndexDO data) {
        var dispatcher = OrderStatusEnum.isWaitDispatch(data.getIndexStatus()) && data.getCarrierId() != null;
        //调度 并且 类型为发货方运单时，状态为待接收
        if (dispatcher && TransportTypeEnum.isCustomer(data.getTransportType())) {
            data.setTransportStatus(TransportStatusEnum.WAIT_ACCEPT.getValue());
        }
        //状态被拆单 已删除
        if (OrderStatusEnum.CLOSE.getValue().equals(data.getIndexStatus())) {
            var split = orderIndexMapper.getPrevOrderId(data.getIndexId());
            Optional.ofNullable(split).ifPresent(a -> {
                data.setTransportStatus(TransportStatusEnum.BE_SPLIT.getValue());
            });
        }

    }

    /**
     * 回单复核
     *
     * @param data
     */
    private void receiptReview(OrderIndexDO data) {
        //已回单
        if (data.isReceipt()) {
            data.setReceiptReview(TransportReceiptReviewEnum.NO.getValue());
            //找到回单复核类型的异常
            var orderException = orderExceptionRepository.getOrderExceptionByOrderId(data.getIndexId());
            var receiptReview = Optional.ofNullable(orderException)
                    .filter(item -> TransportReceiptReviewEnum.isYes(item.getExceptionStatus())).orElse(null);
            Optional.ofNullable(receiptReview).ifPresent(t -> data.setReceiptReview(TransportReceiptReviewEnum.YES.getNewValue()));
        }
    }

    /**
     * 拼车单合同
     *
     * @param data
     */
    private void combinePactCode(OrderIndexDO data) {
        if (LongUtils.notNullLong(data.getOwnerCombinedOrderId())) {
            var combineOrder = orderIndexMapper.selectById(data.getOwnerCombinedOrderId());
            Optional.ofNullable(combineOrder).ifPresent(combine -> data.setCombinedOrderPactCode(combine.getIndexPactcode()));
        }
    }

    @Override
    public void syncRelation() {
        var count = wayBillRepository.count();
        logger.info("运单老数据数据量，size：{}", count);
        var pages = (int) Math.ceil(count * 1.0 / Constants.PAGE_SIZE);
        for (int i = 1; i <= pages; i++) {
            logger.info("开始同步运单关系数据：第{}页，共{}页", i, pages);
            var list = wayBillRepository.list(i);
            list.forEach(data -> {
                try {
                    var order = orderIndexMapper.getById(data.getUp());
                    if (baseOrderRepository.checkTenant(order.getIndexCreatorcompanyid())) {
                        logger.error("运单id：{},租户id:{}", data.getUp(), order.getIndexCreatorcompanyid());
                        baseOrderRepository.sync(null);
                    } else {
                        var upTransportId = Optional.ofNullable(upTransportId(order)).orElse(0L);
                        baseOrderRepository.sync(ScannerTransportRelationAssembler.assemble(TransportRelationConvert.convert(data.getUp(), upTransportId, data.getTenantId())));
                    }
                } catch (Exception e) {
                    logger.error("运单同步关系异常：{},{}", data.getId(), e);
                    e.printStackTrace();
                }
            });
        }
        logger.info("运单关系同步完成......");
    }

    @Override
    public TransportIdRelation getRelationByDownId(Long downTransportId) {
        var order = orderIndexMapper.getById(downTransportId);
        if (baseOrderRepository.checkTenant(order.getIndexCreatorcompanyid())) {
            logger.error("运单id：{},租户id:{}", downTransportId, order.getIndexCreatorcompanyid());
            return null;
        }
        var upTransportId = Optional.ofNullable(upTransportId(order)).orElse(0L);
        return TransportRelationConvert.convert(downTransportId, upTransportId, order.getIndexCreatorcompanyid());
    }

    @Override
    public void getRelationByTenantId(Long tenantId) {
        logger.info("(Index_Status <> -1 and Index_Status <> 0 and Index_SrcClass = 2) or (Index_SrcClass = 1 and Index_SrcOrderID = 0)");
        var count = wayBillRepository.count(tenantId);
        logger.info("租户{}运单老数据数据量，size：{}", tenantId, count);
        var pages = (int) Math.ceil(count * 1.0 / Constants.PAGE_SIZE);
        for (int i = 1; i <= pages; i++) {
            logger.info("开始同步租户{}运单关系数据：第{}页，共{}页", tenantId, i, pages);
            var list = wayBillRepository.list(i, tenantId);
            list.forEach(data -> {
                try {
                    var order = orderIndexMapper.getById(data.getUp());
                    var upTransportId = Optional.ofNullable(upTransportId(order)).orElse(0L);
                    baseOrderRepository.sync(ScannerTransportRelationAssembler.assemble(TransportRelationConvert.convert(data.getUp(), upTransportId, data.getTenantId())));
                } catch (Exception e) {
                    logger.error("运单关系同步异常：{},{}", data.getId(), e);
                    e.printStackTrace();
                }
            });
        }
        logger.info("租户{}运单关系同步完成......", tenantId);
    }

    private static Integer financeStatus(Integer upFinanceStatus, Integer downFinanceStatus) {
        var list = Arrays.asList(upFinanceStatus, downFinanceStatus).stream().filter(x -> x != null).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.stream().reduce(Integer::max).get();
    }

    @Override
    public List<Long> getByTime(String startTime, String endTime) {
        return wayBillRepository.getByTime(startTime, endTime);
    }

    @Override
    public List<Long> getByTenantIdTime(Long tenantId, String startTime, String endTime) {
        return wayBillRepository.getByTenantIdTime(tenantId, startTime, endTime);
    }
}
